package com.waylau.spring.boot.blog.controller;

import java.sql.Date;
import java.util.*;

import com.waylau.spring.boot.blog.domain.Blog;
import com.waylau.spring.boot.blog.domain.Browse;
import com.waylau.spring.boot.blog.domain.Genre;
import com.waylau.spring.boot.blog.service.*;
import com.waylau.spring.boot.blog.vo.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import com.waylau.spring.boot.blog.domain.User;
import com.waylau.spring.boot.blog.domain.es.EsBlog;
import com.waylau.spring.boot.blog.vo.TagVO;
import org.springframework.web.servlet.ModelAndView;

/**
 * 主页控制器.
 *
 * @since 1.0.0 2017年3月8日
 * @author <a href="https://waylau.com">Way Lau</a>
 */
@Controller
@RequestMapping("/blogs")
public class BlogController {

	@Autowired
	private EsBlogService esBlogService;

	@Autowired
	private HotSearchService hotSearchService;

	@Autowired
	private BrowseService browseService;

	@Autowired
	private GenreService genreService;

	@Autowired
	private BlogService blogService;

	@GetMapping
	public String listEsBlogs(
			@RequestParam(value="genre",required = false) String genre,
			@RequestParam(value="order",required=false,defaultValue="new") String order,
			@RequestParam(value="keyword",required=false,defaultValue="" ) String keyword,
			@RequestParam(value="async",required=false) boolean async,
			@RequestParam(value="pageIndex",required=false,defaultValue="0") int pageIndex,
			@RequestParam(value="pageSize",required=false,defaultValue="10") int pageSize,
			Model model) {

		Page<EsBlog> page = null;
		List<EsBlog> list = null;
		boolean isEmpty = true; // 系统初始化时，没有博客数据
		try {
			if (order.equals("hot")) { // 最热查询
				Sort sort = new Sort(Direction.DESC,"readSize","commentSize","voteSize","createTime");
				Pageable pageable = new PageRequest(pageIndex, pageSize, sort);

				if(genre!=null && genre.length()>0){
					page = esBlogService.listHotestEsBlogs(genre,keyword, pageable);
				}else{
					page = esBlogService.listHotestEsBlogs(keyword, pageable);
				}
				if(keyword.length()>0){
					hotSearchService.updateHotSearch(keyword);
				}
			} else if (order.equals("new")) { // 最新查询
				Sort sort = new Sort(Direction.DESC,"createTime");
				Pageable pageable = new PageRequest(pageIndex, pageSize, sort);
				page = esBlogService.listNewestEsBlogs(keyword, pageable);
				if(keyword.length()>0){
					hotSearchService.updateHotSearch(keyword);
				}
			}
			isEmpty = false;
		} catch (Exception e) {
			Pageable pageable = new PageRequest(pageIndex, pageSize);
			page = esBlogService.listEsBlogs(pageable);
		}

		list = page.getContent();	// 当前所在页面数据列表


		model.addAttribute("order", order);
		model.addAttribute("keyword", keyword);
		model.addAttribute("page", page);
		model.addAttribute("blogList", list);

		// 首次访问页面才加载
		if (!async && !isEmpty) {
			List<EsBlog> newest = esBlogService.listTop5NewestEsBlogs();
			model.addAttribute("newest", newest);

			Object object = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			if(!"anonymousUser".equals(object)){

				User user = (User) object;
				List<Browse> browses = browseService.findTop50ByUser(user.getId());
				List<EsBlog> hotest = new ArrayList<EsBlog>();
				//数据量略大才会触发推荐模块
				if(browses.size()<10||page.getTotalElements()<10){
					hotest.addAll(esBlogService.listTop5HotestEsBlogs());
				}else{
					List<Map<String,Object>> genres = new ArrayList<>();
					Map<Long,Integer> genreIds = new HashMap<Long,Integer>();
					browses.forEach(a->{
						if(genreIds.get(a.getGenreId())!=null){
							Map<String,Object> map = genres.get(genreIds.get(a.getGenreId()));
							map.put("num",(Integer)map.get("num")+1);
						}else{
							genreIds.put(a.getGenreId(),genreIds.size());
							Map<String,Object> map = new HashMap<String,Object>();
							map.put("genreId",a.getGenreId());
							map.put("num",1);
							genres.add(map);
						}
					});
					Integer total = 0;
					List<Integer> origin = new ArrayList<>();
					for(int i=0;i<genres.size();i++){
						Map<String,Object> m = genres.get(i);
						genreIds.put((Long)m.get("genreId"),(Integer)m.get("num"));
						int j = (Integer) m.get("num");
						total += j;
						for(int k=0;k<j;k++){
							origin.add(i);
						}
					}
					Set<Map.Entry<Long,Integer>> set = genreIds.entrySet();
					List<Map.Entry<Long,Integer>> sortList = new LinkedList<>(set);
					Collections.sort(sortList, new Comparator<Map.Entry<Long, Integer>>() {
						@Override
						public int compare(Map.Entry<Long, Integer> o1, Map.Entry<Long, Integer> o2) {
							return o2.getValue()-o1.getValue();
						}
					});
					genreIds.clear();
					Random random = new Random();
					for(int i = 0 ;i < 4;i++){
						Long genreId = (Long) genres.get(origin.get(random.nextInt(total))).get("genreId");
						if(genreIds.get(genreId)!=null){
							genreIds.put(genreId,genreIds.get(genreId)+1);
						}else{
							genreIds.put(genreId,1);
						}
					}
					sortList.forEach(a->{
						if(genreIds.get(a.getKey())!=null){
							a.setValue(genreIds.get(a.getKey()));
							blogService.listTopNByGenre(a.getKey(),a.getValue()).forEach(b->{
								hotest.add(new EsBlog(b));
							});
						}
					});
					Integer needLength = 5-hotest.size();
					int i = 0;
					while(i<needLength){
						List<Genre> genreList = genreService.findRandomGenresAndIdNotIn(genreIds.keySet(),1);
						if(genreList.size()>0&&genreIds.get(genreList.get(0).getId())==null){
							genreIds.put(genreList.get(0).getId(),1);
							i++;
							blogService.listTopNByGenre(genreList.get(0).getId(),1).forEach(b->{
								hotest.add(new EsBlog(b));
							});
						}
						if(genreList.size()==0){
							break;
						}
					}
				}
				model.addAttribute("hotest", hotest);
			}else{
				List<EsBlog> hotest = esBlogService.listTop5HotestEsBlogs();
				model.addAttribute("hotest", hotest);
			}
			//List<TagVO> tags = esBlogService.listTop30Tags();
			//model.addAttribute("tags", tags);
			List<User> users = esBlogService.listTop12Users();
			model.addAttribute("users", users);
		}
		return (async==true?"/index :: #mainContainerRepleace":"/index");
	}

	@GetMapping("/newest")
	public String listNewestEsBlogs(Model model) {
		List<EsBlog> newest = esBlogService.listTop5NewestEsBlogs();
		model.addAttribute("newest", newest);
		return "newest";
	}

	@GetMapping("/hotest")
	public String listHotestEsBlogs(Model model) {
		List<EsBlog> hotest = esBlogService.listTop5HotestEsBlogs();
		model.addAttribute("hotest", hotest);
		return "hotest";
	}

	@GetMapping("/hotSearch")
	public ResponseEntity<Response> hotSearch() {
		return ResponseEntity.ok().body(new Response(true,"成功",hotSearchService.getHotSearch()));
	}

	/**
	 * 获得7天内博客点赞前5的点赞数据
	 * @return
	 */
	@GetMapping("/voteStatistics")
	public ModelAndView voteStatistics(Model model) {
		HashMap map = blogService.voteTop5();
		model.addAttribute("top5",map.entrySet());
		return new ModelAndView("statistics/blogVote", "voteModel", model);
	}


	/**
	 * 查询
	 * @return
	 */
	@GetMapping("/list")
	public ModelAndView list(@RequestParam(value="async",required=false) boolean async,
							 @RequestParam(value="pageIndex",required=false,defaultValue="0") int pageIndex,
							 @RequestParam(value="pageSize",required=false,defaultValue="10") int pageSize,
							 @RequestParam(value="name",required=false,defaultValue="") String name,
							 Model model) {

		Pageable pageable = new PageRequest(pageIndex, pageSize);
		Page<Blog> page = blogService.listBlogsByTitle(name,pageable);
		List<Blog> list = page.getContent();	// 当前所在页面数据列表

		model.addAttribute("page", page);
		model.addAttribute("blogList", list);
		return new ModelAndView(async==true?"blog-back/list :: #mainContainerRepleace":"blog-back/list", "blogModel", model);
	}

	/**
	 * 删除
	 * @param id
	 * @return
	 */
	@DeleteMapping(value = "/{id}")
	@PreAuthorize("hasAuthority('ROLE_ADMIN')")
	public ResponseEntity<Response> delete(@PathVariable("id") Long id, Model model) {
		try {
			blogService.removeBlog(id);
		} catch (Exception e) {
			e.printStackTrace();
			return  ResponseEntity.ok().body( new Response(false, e.getMessage()));
		}
		return  ResponseEntity.ok().body( new Response(true, "处理成功"));
	}
}
